﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.Collections.Generic;
using ADOX;
using System.Reflection;

namespace PlanningGIS.Util.Data
{
    /// <summary>
    /// 数据表操作类
    /// </summary>
    public class DataTableHelper
    {
        /// <summary>
        /// 求两个System.Data.DataTable的交集集合  
        /// </summary>
        /// <param name="table1">表1</param>
        /// <param name="table2">表2</param>
        /// <returns></returns>
        public static System.Data.DataTable Intersect(System.Data.DataTable table1, System.Data.DataTable table2)
        {
            if (table1 == null && table2 == null) return null;
            if (table1 == null || table2 == null) return null;
            System.Data.DataTable dtNew = table1.Copy();
            System.Data.DataTable dtOld = table2;
            IEnumerable<System.Data.DataRow> query = dtOld.AsEnumerable().Intersect(table1.AsEnumerable(), DataRowComparer.Default);
            dtNew = query.CopyToDataTable();
            return dtNew;
        }

        /// <summary>
        /// 求两个System.Data.DataTable的并集集合
        /// </summary>
        /// <param name="table1">表1</param>
        /// <param name="table2">表2</param>
        /// <returns></returns>
        public static System.Data.DataTable Union(System.Data.DataTable table1, System.Data.DataTable table2)
        {
            if (table1 == null && table2 == null) return null;
            if (table1 == null && table2 != null) return table2;
            if (table1 != null && table2 == null) return table1;
            System.Data.DataTable dtNew = table1.Copy();
            System.Data.DataTable dtOld = table2;
            IEnumerable<System.Data.DataRow> query = dtOld.AsEnumerable().Union(table1.AsEnumerable(), DataRowComparer.Default);
            dtNew = query.CopyToDataTable();
            return dtNew;
        }

        /// <summary>
        /// 求两个System.Data.DataTable的差集集合
        /// </summary>
        /// <param name="table1">表1</param>
        /// <param name="table2">表2</param>
        /// <returns></returns>
        public static System.Data.DataTable Except(System.Data.DataTable table1, System.Data.DataTable table2)
        {
            if (table1 == null && table2 == null) return null;
            if (table1 == null && table2 != null) return table2;
            if (table1 != null && table2 == null) return table1;
            System.Data.DataTable dtNew = table1.Copy();
            System.Data.DataTable dtOld = table2;
            IEnumerable<System.Data.DataRow> query = dtOld.AsEnumerable().Except(table1.AsEnumerable(), DataRowComparer.Default);
            dtNew = query.CopyToDataTable();
            return dtNew;
        }

        /// <summary>
        /// 将数据表对象转成指定类型的对象
        /// </summary>
        /// <typeparam name="T">要转换的类型</typeparam>
        /// <param name="datatable">数据表</param>
        /// <returns></returns>
        public static List<T> ToObject<T>(System.Data.DataTable datatable)
        {
            if (datatable == null || datatable.Rows.Count == 0) return null;
            List<T> objs = new List<T>();
            foreach (System.Data.DataRow row in datatable.Rows)
            {
                T obj = Activator.CreateInstance<T>();
                Type type = obj.GetType();
                FieldInfo[] fds = type.GetFields();
                PropertyInfo[] pis = type.GetProperties();
                List<string> names = new List<string>();
                foreach (PropertyInfo pi in pis)
                {
                    if (!pi.CanWrite) continue;
                    string name = pi.Name;
                    if (names.Contains(name)) continue;
                    if (!datatable.Columns.Contains(name)) continue;
                    if (row[name] == null || row[name] == DBNull.Value) continue;
                    if (pi.PropertyType == typeof(Int16) || pi.PropertyType == typeof(Int32) || pi.PropertyType == typeof(Int64) ||
                        pi.PropertyType == typeof(UInt16) || pi.PropertyType == typeof(UInt32) || pi.PropertyType == typeof(UInt64))
                    {
                        pi.SetValue(obj, int.Parse(row[name].ToString()), null);
                    }
                    else if (pi.PropertyType == typeof(Double) || pi.PropertyType == typeof(Single))
                    {
                        pi.SetValue(obj, double.Parse(row[name].ToString()), null);
                    }
                    else if (pi.PropertyType == typeof(Decimal))
                    {
                        pi.SetValue(obj, decimal.Parse(row[name].ToString()), null);
                    }
                    else if (pi.PropertyType == typeof(DateTime))
                    {
                        pi.SetValue(obj, DateTime.Parse(row[name].ToString()), null);
                    }
                    else
                    {
                        pi.SetValue(obj, row[name], null);
                    }
                }
                foreach (FieldInfo fi in fds)
                {
                    string name = fi.Name;
                    if (names.Contains(name)) continue;
                    if (!datatable.Columns.Contains(name)) continue;
                    if (row[name] == null || row[name] == DBNull.Value) continue;
                    if (fi.FieldType == typeof(Int16) || fi.FieldType == typeof(Int32) || fi.FieldType == typeof(Int64) || fi.FieldType == typeof(UInt16) || fi.FieldType == typeof(UInt32) || fi.FieldType == typeof(UInt64))
                    {
                        fi.SetValue(obj, int.Parse(row[name].ToString()));
                    }
                    else if (fi.FieldType == typeof(Double) || fi.FieldType == typeof(Single))
                    {
                        fi.SetValue(obj, double.Parse(row[name].ToString()));
                    }
                    else if (fi.FieldType == typeof(Decimal))
                    {
                        fi.SetValue(obj, decimal.Parse(row[name].ToString()));
                    }
                    else if (fi.FieldType == typeof(DateTime))
                    {
                        fi.SetValue(obj, DateTime.Parse(row[name].ToString()));
                    }
                    else
                    {
                        fi.SetValue(obj, row[name]);
                    }
                }
                objs.Add(obj);
            }
            return objs;
        }

    }
}
